fix(formula): catch unknown functions in CEL conditions at build (#1877)#1896
Merged
Conversation
cel-js's `check()` returns a `TypeCheckResult` object (`{ valid, error }`),
not an array, so `compile()`'s `Array.isArray(checkErrors)` guard never
matched and the type-check verdict was silently discarded. A condition
calling an unknown function (`PRIOR(status)`, a typo'd `isBlnk(...)`)
type-checks as `found no matching overload`, but that result never
surfaced — so `objectstack compile`, `registerFlow`, and the
`validate_expression` tool all accepted the predicate, which then
silently no-op'd the flow at runtime.
Read the documented `{ valid, error }` shape instead. Because every
author surface routes through this one `compile()`, the fix closes the
gap for flow conditions, validation rules, and field formulas at once.
Verified cel-js's `check()` cleanly separates valid predicates from
unknown-function ones with no false positives on existing conditions.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1877.
Problem
A flow whose trigger/edge condition calls an unknown function —
PRIOR(status), a typo'disBlnk(...)— was silently accepted: build + typecheck pass, then the broken condition no-op'd the flow at runtime with no log line. The reporter hit this on@objectstack9.5.1 while runtime-testing theobjectstack-ai/templatesset (signal_to_topic_promotion,cta_creation_default).Root cause
In
packages/formula/src/cel-engine.ts,compile()discarded the type-check verdict:cel-js's
check()returns aTypeCheckResultobject ({ valid, type?, error? }), never an array — soArray.isArray(...)was always false and the verdict was dropped. An unknown function type-checks asfound no matching overload for 'PRIOR(dyn)', but that result never surfaced. Every author surface (objectstack compileviavalidate-expressions.ts,registerFlow'svalidateFlowExpressions, and the agentvalidate_expressiontool) routes through this onecompile(), so all of them accepted the predicate.Fix
Read the documented
{ valid, error }shape. One change closes the gap for flow conditions, validation rules, and field formulas at once.The runtime half of the issue is already loud on current
main(post-ADR-0032): the unknown-function fault messagefound no matching overloaddoesn't match theno such overloadnumeric-retry guard, so it propagates as an attributed flow failure rather thanreturn false. The reporter's silent skip was on 9.5.1, which predates that work — but build validation stayed broken until this change.Verification
check()cleanly separates valid predicates (record.rating >= 4,!isBlank(...),previous.status != null, every existing example flow condition) from unknown-function ones — no false positives.cel-engine.test.tsandvalidate.test.ts(PRIOR(), short-circuit-guarded unknown call, typo'disBlnk, plus assertions that registered stdlibisBlankstill passes).@objectstack/formula95 passed ·@objectstack/service-automation187 passed ·tsc --noEmitclean.🤖 Generated with Claude Code